#region Copyright
/// <copyright>
/// Copyright (c) 2007 Ilia Shramko.
/// Released under the terms of the GNU General Public License.
/// </copyright>
#endregion

using System;
using System.Collections.Generic;
using System.Text;

namespace Osh.Teletext
{
	public class RowState : IComparable
	{
		public const int DefaultForegroundColor = 7;
		public const int DefaultBackgroundColor = 0;

		public int Color;
		public bool Flash;
		public bool MosaicMode;
		public bool IsMosaicChar;
		public bool Conceal;
		public bool SeparatedMosaic;
		public bool SecondG0Set;
		public int BackgroundColor;
		public bool HoldMosaic;

		public RowState()
		{
			Clear();
		}

		public RowState(RowState state)
		{
			Clear();
			this.Color = state.Color;
			this.MosaicMode = state.MosaicMode;
			this.IsMosaicChar = state.IsMosaicChar;
			this.BackgroundColor = state.BackgroundColor;
			this.Conceal = state.Conceal;
			this.SeparatedMosaic = state.SeparatedMosaic;
			this.SecondG0Set = state.SecondG0Set;
			this.HoldMosaic = state.HoldMosaic;
		}

		public void UpdateBefore(int ch)
		{
			if(ch == 9) // Steady
			{
				Flash = false;
			}
			else if(ch == 0x18)	// Conceal
			{
				Conceal = true;
			}
			else if(ch == 0x1C)	// Black Background
			{
				BackgroundColor = 0;
			}
			else if(ch == 0x1D)	// New Background
			{
				BackgroundColor = Color;
			}
			else if(ch == 0x1E)	// Hold Mosaics ("Set-At")
			{
				HoldMosaic = true;
			}

			IsMosaicChar = this.MosaicMode && (ch <= 0x3F || (ch >= 0x60 && ch <= 0x7F)); // Includes chars < 0x20, because they can be replaced by the Held Char.
		}

		public void UpdateAfter(int ch)
		{
			if(ch >= 0 && ch <= 7)	// alpha color
			{
				MosaicMode = false;
				Color = ch;
				Conceal = false;
			}
			else if(ch == 8)
			{
				Flash = true;
			}
			else if(ch >= 0x10 && ch <= 0x17)	// mosaic color
			{
				MosaicMode = true;
				Color = ch - 0x10;
				Conceal = false;
			}
			else if(ch == 0x1B)
			{
				MosaicMode = false;
			}
			else if(ch == 0x1F)	// Release Mosaics ("Set-After")
			{
				HoldMosaic = false;
			}
		}

		public void Clear()
		{
			Color = DefaultForegroundColor;
			Flash = false;
			MosaicMode = false;
			IsMosaicChar = false;
			BackgroundColor = DefaultBackgroundColor;
			Conceal = false;
			SeparatedMosaic = false;
			SecondG0Set = false;
			HoldMosaic = false;
		}


		#region IComparable Members & Stuff
		public int CompareTo(object obj)
		{
			RowState otherObj = (RowState)obj;
			if(this.Color > otherObj.Color) return 1;
			if(this.Color < otherObj.Color) return -1;
			if(this.MosaicMode && !otherObj.MosaicMode) return 1;
			if(!this.MosaicMode && otherObj.MosaicMode) return -1;
			if(this.IsMosaicChar && !otherObj.IsMosaicChar) return 1;
			if(!this.IsMosaicChar && otherObj.IsMosaicChar) return -1;
			if(this.BackgroundColor > otherObj.BackgroundColor) return 1;
			if(this.BackgroundColor < otherObj.BackgroundColor) return -1;
			if(this.Conceal && !otherObj.Conceal) return 1;
			if(!this.Conceal && otherObj.Conceal) return -1;
			if(this.SeparatedMosaic && !otherObj.SeparatedMosaic) return 1;
			if(!this.SeparatedMosaic && otherObj.SeparatedMosaic) return -1;
			if(this.SecondG0Set && !otherObj.SecondG0Set) return 1;
			if(!this.SecondG0Set && otherObj.SecondG0Set) return -1;
			if(this.HoldMosaic && !otherObj.HoldMosaic) return 1;
			if(!this.HoldMosaic && otherObj.HoldMosaic) return -1;

			return 0;
		}

		public override int GetHashCode()
		{
			return 0;
		}

		public override bool Equals(object obj)
		{
			if(obj == null)
				return false;

			if(!(obj is RowState))
				return false;

			return this.CompareTo(obj) == 0;
		}

		public bool Equals(RowState obj)
		{
			if((object)obj == null)
				return false;

			return this.CompareTo(obj) == 0;
		}

		public static bool operator ==(RowState a, RowState b)
		{
			if(object.ReferenceEquals(a, b))
				return true;

			if(((object)a == null) || ((object)b == null))
				return false;

			return a.Equals(b);
		}

		public static bool operator !=(RowState a, RowState b)
		{
			return !(a == b);
		}
		#endregion IComparable Members & Stuff
	}
}
